import sys
import os
# 导入 PyQt6 相关模块
from PyQt6.QtWidgets import QApplication, QMessageBox
from PyQt6.QtCore import QSharedMemory, QSystemSemaphore, QTimer # QTimer 用于延迟激活
from PyQt6.QtNetwork import QLocalServer, QLocalSocket # 恢复导入

# --- 尝试导入 win32gui 用于窗口激活 (仍然需要查找窗口，但激活由 IPC 完成) ---
try:
    import win32gui
    import win32con
except ImportError:
    win32gui = None
    win32con = None
    print("警告: 未找到 pywin32 库，无法通过快捷方式激活已运行窗口。请运行 'pip install pywin32' 安装。")
# -------------------------------------

# --- 移除旧的 resource_path 函数，因为它现在由 alarm_manager 处理数据路径 ---
# def resource_path(relative_path):
#     try:
#         base_path = sys._MEIPASS
#     except Exception:
#         base_path = os.path.abspath(os.path.dirname(__file__))
#     return os.path.join(base_path, relative_path)

# 导入主窗口类
from ui.main_window import MainWindow

# 定义窗口标题，用于查找 - 确保与 MainWindow 设置的一致
WINDOW_TITLE = "桌面闹钟"
# 定义用于 IPC 的唯一标识符 (基于之前的 unique_key)
IPC_KEY = f"DesktopAlarmClockApp_IPC_{WINDOW_TITLE}_f2a4e113" # IPC 使用不同的 key

def main():
    # --- 单例模式实现 (使用共享内存检测) ---
    # 注意：这里的 unique_key 只用于共享内存检测，IPC 使用 IPC_KEY
    unique_key_sm = f"DesktopAlarmClockApp_Mutex_{WINDOW_TITLE}_f2a4e113_SM" # 共享内存 key

    # SystemSemaphore 不再需要，因为激活由 IPC 处理，共享内存足够判断实例是否存在
    shared_memory = QSharedMemory(unique_key_sm)
    is_running = False

    # 尝试附加到共享内存以检查实例是否存在
    if shared_memory.attach(QSharedMemory.AccessMode.ReadOnly):
        is_running = True
        shared_memory.detach() # 检查完就分离
    else:
        # 附加失败，尝试创建 (我们是第一个实例)
        if not shared_memory.create(1):
             # 如果创建失败，检查是否是因为已存在 (异常情况)
             if shared_memory.error() == QSharedMemory.Error.AlreadyExists:
                 print("警告: 共享内存已存在，但之前附加失败。可能状态异常。假定有实例在运行。")
                 is_running = True # 假设实例在运行，让 IPC 去尝试激活
             else:
                 print(f"错误: 无法创建共享内存段: {shared_memory.errorString()}")
                 QMessageBox.critical(None, "启动错误", f"无法创建共享内存段: {shared_memory.errorString()}")
                 sys.exit(1)
        # 创建成功，我们是第一个实例，需要持有共享内存直到退出

    # 如果已有实例在运行
    if is_running:
        print("检测到已运行实例，通过 IPC 发送激活信号...")
        socket = QLocalSocket()
        socket.connectToServer(IPC_KEY)

        if socket.waitForConnected(500): # 等待最多 500ms 连接
            print("成功连接到运行中的实例。发送激活信号。")
            # 发送一个简单的激活信号 (内容不重要，连接本身就是信号)
            socket.write(b'activate')
            socket.waitForBytesWritten(100) # 等待写入完成
            socket.disconnectFromServer()
            sys.exit(0) # 成功发送信号，退出当前 (第二个) 实例
        else:
            print(f"错误: 无法连接到运行中实例的 IPC 服务器 (Key: {IPC_KEY})。错误: {socket.errorString()}")
            # 尝试使用 win32gui 作为后备方案（虽然可能效果不佳）
            if win32gui and win32con:
                 print("尝试使用 win32gui 作为后备方案激活窗口...")
                 try:
                      hwnd = win32gui.FindWindow(None, WINDOW_TITLE)
                      if hwnd:
                           if win32gui.IsIconic(hwnd):
                                win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
                           win32gui.SetForegroundWindow(hwnd)
                           print("已尝试后备激活。")
                           sys.exit(0) # 无论是否成功，退出
                      else:
                           print("后备方案: 未找到窗口。")
                 except Exception as e_fallback:
                      print(f"后备激活失败: {e_fallback}")

            # 如果连接失败，提示用户
            temp_app = QApplication.instance() or QApplication(sys.argv)
            QMessageBox.warning(None, "激活失败",
                                f"无法连接到正在运行的 '{WINDOW_TITLE}' 实例以激活窗口。\n请手动切换到该窗口。")
            sys.exit(1) # 退出第二个实例
    # ---------------------\

    # --- 如果是第一个实例，则启动 QApplication 和 IPC 服务器 ---
    print("启动新的应用程序实例和 IPC 服务器...")
    app = QApplication(sys.argv)

    # 确保共享内存在退出时分离
    def cleanup_shm():
        if shared_memory.isAttached():
            shared_memory.detach()
            print("共享内存已分离。")
    app.aboutToQuit.connect(cleanup_shm)

    # 实例化主窗口
    window = MainWindow()
    # window.setWindowTitle(WINDOW_TITLE) # MainWindow 内部已经设置了

    # --- 设置 QLocalServer 监听激活信号 ---
    server = QLocalServer()

    # 处理新连接的槽函数
    def handle_activation_request():
        print("IPC 服务器收到连接请求 (激活信号)。")
        client_connection = server.nextPendingConnection()
        if client_connection:
            # 读取并丢弃可能的 'activate' 消息 (可选)
            client_connection.waitForReadyRead(100)
            client_connection.readAll()
            client_connection.disconnectFromServer()

            # 延迟调用激活，确保事件循环有机会处理
            QTimer.singleShot(50, window.activate_window)
            print("已调用 window.activate_window()")

    server.newConnection.connect(handle_activation_request)

    # 尝试监听，如果失败则清理并退出
    # 先尝试移除旧的服务器实例 (如果存在且未正确关闭)
    QLocalServer.removeServer(IPC_KEY)
    if not server.listen(IPC_KEY):
        print(f"错误: 无法启动 IPC 服务器监听 (Key: {IPC_KEY}): {server.errorString()}")
        # 再次尝试移除以防万一
        QLocalServer.removeServer(IPC_KEY)
        if not server.listen(IPC_KEY):
            QMessageBox.critical(None, "启动错误", f"无法启动本地服务器监听：\n{server.errorString()}\n\n请确保没有其他程序占用了标识符，或尝试重启。")
            if shared_memory.isAttached(): shared_memory.detach() # 清理共享内存
            sys.exit(1)

    # print(f"IPC 服务器正在监听: {server.serverName()}") # <-- Comment out for release

    # --- 确保服务器在退出时关闭 ---
    def cleanup_server():
        if server.isListening():
            server.close()
            # 再次移除，确保下次能正常启动
            QLocalServer.removeServer(IPC_KEY)
            print("IPC 服务器已关闭。")
    app.aboutToQuit.connect(cleanup_server)
    # --------------------------------

    window.show()
    app.setQuitOnLastWindowClosed(False) # 保持后台运行

    exit_code = app.exec()
    print(f"应用程序事件循环结束，退出码: {exit_code}")
    sys.exit(exit_code)

if __name__ == '__main__':
    main()